home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / jam / jamdisk1 / bio / source.run / dates.h < prev    next >
Encoding:
C/C++ Source or Header  |  1992-07-07  |  5.9 KB  |  187 lines

  1. /*
  2.    Functions for date calculation and conversion.  Inspired by DATE.C from
  3.    John A. Hodgson, and a need for date calculation routines in an upcoming
  4.    project.  These routines should be error-free until the beginning of the
  5.    22nd century.  Please see the text above each routine for notes and comments
  6.    on usage.  I've spent much time developing and testing these routines.
  7.  
  8. */
  9.  
  10.  
  11. typedef struct JULDATE {
  12.     short  year;
  13.     short  days;
  14.     };
  15.  
  16. short days_before[12] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
  17.     /*  # of days preceding each month  */
  18.  
  19. /*
  20.     The following routine accepts one argument, a pointer to a JULDATE
  21.     structure.  It returns the current date in Julian date form.
  22. */
  23.  
  24. void Get_Date(date)
  25. struct JULDATE *date;
  26. {
  27.     long datestmp[3];
  28.     int junk, year_span, years_left, remainder, leapdays;
  29.  
  30.     junk = DateStamp(&datestmp[0]);        /*  get the date  */
  31.     datestmp[0] += 1;            /*  add 1 for Jan. 1, 1978  */
  32.     year_span = datestmp[0] / 366;        /*  approx. year  */
  33.     date->days = datestmp[0] % 366;        /*  # of days left over  */
  34.     leapdays = year_span / 4;        /*  approx. # of leap days  */
  35.     date->year = 1978 + year_span;        /*  current year  */
  36.     years_left = year_span % 4;        /*  years since last leap yr  */
  37.     remainder = date->year % 4;    /*  # of years since last leap  */
  38.     if (remainder <= years_left && remainder > 0)
  39.         leapdays += 1;        /*  recent year was a leap year  */
  40.     date->days += year_span - leapdays;    /*  correct for leap days  */
  41.     if (remainder > 0 && date->days > 365)
  42.         {
  43.         date->year += 1;
  44.         date->days -= 365;
  45.         }
  46.     else if (remainder == 0 && date->days > 366)
  47.         {
  48.         date->year += 1;
  49.         date->days -= 366;
  50.         }
  51. }
  52.  
  53. /*
  54.     This function accepts two arguments:  a string pointer and a pointer to a
  55.     JULDATE structure.  The routine will convert the Julian date to Gregorian
  56.     (mm-dd-yyyy) format.  The string pointer must point to a space at least
  57.     11 characters long.
  58. */
  59.  
  60. void JultoGreg(greg_date, date)
  61. char *greg_date;
  62. struct JULDATE *date;
  63. {
  64.     int length, year, month, day;
  65.     short julday;
  66.     char string[6];
  67.  
  68.     year = date->year;
  69.     julday = date->days;
  70.     if ( !(year % 4) && julday > 60)  julday -= 1;
  71.         /*  subtract 1 if we are in a leap year & past Feb.  */
  72.     for (month = 0; (days_before[month] < julday) && (month < 12); month++);
  73.         /*  find month  */
  74.     day = julday - days_before[month-1];    /*  get current day  */
  75.     length = stci_d(greg_date, month, 11);    /*  month into greg_date  */
  76.     strcat(greg_date, "-");
  77.     length = stci_d(string, day, 6);
  78.     strcat(greg_date, string);        /*  add day to greg_date  */
  79.     strcat(greg_date, "-");
  80.     length = stci_d(string, year, 6);
  81.     strcat(greg_date, string);        /*  add year to greg_date  */    
  82. }
  83.  
  84. /*
  85.     The following function accepts two arguments:  A pointer to a JULDATE
  86.     structure and a pointer to a string.  It evaluates the string to determine
  87.     if it is a valid date, then converts it to Julian form and returns the
  88.     value in the JULDATE structure.  If the date is invalid, the year element
  89.     of the JULDATE structure will be 0.  It is not 100% accurate in its date-
  90.     checking, as it only checks to make sure that the date is not greater than
  91.     31, without checking what the maximum value should be for that month.  The
  92.     Julian date returned *will* be valid, however, if not correct.
  93.  
  94.     NOTE:  The Gregorian date passed to this routine can be in mm-dd-yy OR
  95.            mm-dd-yyyy form.  The century will automatically be added if the
  96.        form is the former.  (no pun intended)
  97. */
  98.  
  99. void GregtoJul(date, greg_date)
  100. struct JULDATE *date;
  101. char *greg_date;
  102. {
  103.     extern char *stpblk();        /*  standard string functions that  */
  104.                     /*  strips leading spaces        */
  105.     int month, day, year;
  106.     short count;
  107.     char *stptr;
  108.  
  109.     date->year = 0;                /*  will be 0 if date invalid */
  110.     stptr = stpblk(greg_date);        /*  advance past any blanks  */
  111.     count = stcd_i(stptr, &month);        /*  extract month #  */
  112.     stptr += count;
  113.     if ( (stptr[0] == '-' || stptr[0] == '/') && month >= 1 && month <= 12)
  114.         {
  115.         stptr += 1;            /*  skip delimiter  */
  116.         count = stcd_i(stptr, &day);
  117.         stptr += count;
  118.         if ((stptr[0] == '-' || stptr[0] == '/') && day >=1 && day <=31)
  119.             {
  120.             stptr += 1;        /*  skip delimiter  */
  121.             count = stcd_i(stptr, &year);
  122.             if ( year > 0 )
  123.                 {
  124.                 if ( year < 100 )
  125.                     year += 1900;    /*  only got 2 digits */
  126.                 date->year = year;
  127.                 date->days = days_before[month - 1];
  128.                 date->days += day;
  129.                 if (!(year % 4) && month > 2)    /*  > Feb  */
  130.                     date->days += 1;    /*  leap year */
  131.                 }
  132.             }
  133.         }
  134. }
  135.  
  136. /*
  137.     The following function accepts two arguments, both pointers to JULDATE
  138.     structures.  The routine calculates the number of days between the two
  139.     dates and returns the result as an integer.  If the first date is earlier
  140.     than the second, the value returned will be positive.  If the second date
  141.     is earlier than the first, the value returned will be negative.
  142.  
  143.     NOTE TO 8/16 BIT USERS:  int on the Amiga (and presumably any 16/32 bit
  144.     machine) declares a 32-bit integer.  I use int here for clarity, but if
  145.     the default size of int on your machine is 16-bit, you will have to
  146.     declare days1 & days2 as long.
  147. */
  148.  
  149. int Date_Span(date1, date2)
  150. struct JULDATE *date1, *date2;
  151. {
  152.     int days1, days2;
  153.  
  154.     days1 = (date1->year - 1) * 365 + (date1->year - 1) / 4 + date1->days;
  155.     days2 = (date2->year - 1) * 365 + (date2->year - 1) / 4 + date2->days;
  156.     return (days2 - days1);
  157. }
  158.  
  159. /*
  160.     The following function accepts a pointer to a JULDATE structure and 
  161.     returns an integer that is the current day of the month.  It also assigns
  162.     to num the number of days in the current month, and to mn the month #.
  163. */
  164.  
  165. int Datestat(date, num, mn)
  166. struct JULDATE *date;
  167. int *num, *mn;
  168. {
  169.     int month;
  170.     short julday;
  171.  
  172.     julday = date->days;
  173.     if (date->year % 4 == 0 && julday > 60) julday -= 1;
  174.     for (month = 0; (days_before[month] < julday) && (month < 12); month++);
  175.         /*  find month  */
  176.     if (month == 12)
  177.         *num = 31;
  178.     else
  179.         {
  180.         *num = days_before[month] - days_before[month - 1];
  181.         if (date->year % 4 == 0 && month == 2)
  182.             *num += 1;
  183.         }
  184.     *mn = month;
  185.     return(julday - days_before[month-1]);
  186. }
  187.